#include "sbignum.h"
#include <stdlib.h>

// 释放有符号大数
void sbignum_free(sbignum_t* num) {
    bignum_free(&num->num);
}

// 复制有符号大数，将b复制到a
void sbignum_cpy(sbignum_t* a, sbignum_t* b) {
    bignum_cpy(&a->num, &b->num);
    a->neg = b->neg;
}

// 比较有符号大数的大小，返回1表示a>b，返回0表示a=b，返回-1表示a<b
int sbignum_compare(sbignum_t* a, sbignum_t* b) {
    if(a->neg != b->neg) {
        if(bignum_compare(&a->num, &bignum_zero) == 0 && bignum_compare(&b->num, &bignum_zero) == 0) {
            return 0;
        }
    }
    if(a->neg == 0 && b->neg == 0) {
        return bignum_compare(&a->num, &b->num);
    } else if(a->neg != 0 && b->neg == 0) {
        return -1;
    } else if(a->neg == 0 && b->neg != 0) {
        return 1;
    } else if(a->neg != 0 && b->neg != 0) {
        return - bignum_compare(&a->num, &b->num);
    }
    abort();
}

// 有符号大数加法，不改变原有大数值
void sbignum_add(sbignum_t* p, sbignum_t* q, sbignum_t* res) {
    if(p->neg == 0 && q->neg == 0) {
        bignum_add(&p->num, &q->num, &res->num);
        res->neg = 0;
    } else if(p->neg != 0 && q->neg == 0) {
        if(bignum_compare(&p->num, &q->num) > 0) {
            bignum_sub(&p->num, &q->num, &res->num);
            res->neg = 1;
        } else {
            bignum_sub(&q->num, &p->num, &res->num);
            res->neg = 0;
        }
    } else if(p->neg == 0 && q->neg != 0) {
        if(bignum_compare(&p->num, &q->num) < 0) {
            bignum_sub(&q->num, &p->num, &res->num);
            res->neg = 1;
        } else {
            bignum_sub(&p->num, &q->num, &res->num);
            res->neg = 0;
        }
    } else if(p->neg != 0 && q->neg != 0) {
        bignum_add(&p->num, &q->num, &res->num);
        res->neg = 1;
    }
}

// 有符号大数减法，不改变原来的大数
void sbignum_sub(sbignum_t* a, sbignum_t* b, sbignum_t* res) {
    if(a->neg == 0 && b->neg == 0) {
        if(bignum_compare(&a->num, &b->num) >= 0) {
            bignum_sub(&a->num, &b->num, &res->num);
            res->neg = 0;
        } else {
            bignum_sub(&b->num, &a->num, &res->num);
            res->neg = 1;
        }
    } else if(a->neg != 0 && b->neg == 0) {
        bignum_add(&a->num, &b->num, &res->num);
        res->neg = 1;
    } else if(a->neg == 0 && b->neg != 0) {
        bignum_add(&a->num, &b->num, &res->num);
        res->neg = 0;
    } else {
        if(bignum_compare(&a->num, &b->num) > 0) {
            bignum_sub(&a->num, &b->num, &res->num);
            res->neg = 1;
        } else {
            bignum_sub(&b->num, &a->num, &res->num);
            res->neg = 0;
        }
    }
}

// 有符号大数乘法，不改变原大数的值
void sbignum_mul(sbignum_t* p, sbignum_t* q, sbignum_t* res) {
    bignum_mul(&p->num, &q->num, &res->num);
    if(p->neg == q->neg) {
        res->neg = 0;
    } else {
        res->neg = 1;
    }
}
